// Version 2.2
// C#
// Accept control other than a Form
// You can add your own print functions for specific controls and for report title formatting
// Controls can expand
// Expendable TextBox multiline added
// Expandable ListBox added
// Expendable FlexGrid added (Grid from Component One : code in comments only [no references] )
// DataGrid printing
// More comments in source code
// Report printed can continue on many pages
// Can display a trace of controls printed
// Can print page number using your own String.Format
// Report can be print to a multiframe Tif file (example: for faxing)
// Better algorithm to compute extension of container control with rezizable side by side childs
// Test

using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Collections;
using System.Windows.Forms;
using System.Data;
using System.Drawing.Imaging;

namespace FormPrinting
{

	public class FormPrinting
	{
	#region "public section"
		// publics property that can be changed
		public bool TextBoxBoxed = false; // box around TextBox controls
		public bool TabControlBoxed = true; // box around TabControl controls
		public bool LabelInBold = true; // Print all labels in bold
		public bool PrintPreview = true; // enabled Print preview instead of direct printing
		public bool DisabledControlsInGray = false; // Color for disabled controls
		public bool PageNumbering = false; //If true, reserve space at the bottom of each page and print page number
		public string PageNumberingFormat = "Page {0}"; // String format for page number
		public OrientationENum Orientation = OrientationENum.Automatic; // choose print orientation (Automatic, Protrait or Landscape)
		public ControlPrinting DelegatePrintingReportTitle; // Function that will print report title. Can be changed
		//public bool ControlsCanExpand = true; // Indicate if class accept control's expansion
		public Single TopMargin = 0; //If 0, use default margin, else use this
		public Single BottomMargin = 0; //If 0, use default margin, else use this
		public HorizontalAlignment HAlignment = HorizontalAlignment.Center;

		public enum OrientationENum
		{
			Automatic = 1,
			Portrait = 2,
			Lanscape = 3
		}

		public enum ParentControlPrinting
		{
			BeforeChilds = 1,
			AfterChilds = 2,
		}

		// delegate for providing of print function by control type
		public delegate void  ControlPrinting(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls);

		//Constructor
		public FormPrinting(System.Windows.Forms.Control f)
		{
			_f = f;
			_TextBoxLikeControl = new ArrayList();
			_DelegatesforControls = new ArrayList();
			_Pen = new Pen(Color.Black);

			// add build-in types and functions

			AddTextBoxLikeControl("ComboBox");
			AddTextBoxLikeControl("DateTimePicker");
			AddTextBoxLikeControl("DateTimeSlicker");
			AddTextBoxLikeControl("NumericUpDown");

			AddDelegateToPrintControl("TextBox", new ControlPrinting(PrintTextBox));
			AddDelegateToPrintControl("System.Windows.Forms.Label", new ControlPrinting(PrintLabel));
            AddDelegateToPrintControl("System.Windows.Forms.Button", new ControlPrinting(PrintButton));
			AddDelegateToPrintControl("System.Windows.Forms.CheckBox", new ControlPrinting(PrintCheckBox));
			AddDelegateToPrintControl("System.Windows.Forms.RadioButton", new ControlPrinting(PrintRadioButton));
			AddDelegateToPrintControl("System.Windows.Forms.GroupBox", new ControlPrinting(PrintGroupBox));
			AddDelegateToPrintControl("System.Windows.Forms.Panel", new ControlPrinting(PrintPanel));
			AddDelegateToPrintControl("System.Windows.Forms.TabControl", new ControlPrinting(PrintTabControl));
			AddDelegateToPrintControl("System.Windows.Forms.PictureBox", new ControlPrinting(PrintPictureBox));
			AddDelegateToPrintControl("System.Windows.Forms.ListBox", new ControlPrinting(PrintListBox));
			AddDelegateToPrintControl("System.Windows.Forms.DataGrid", new ControlPrinting(PrintDataGrid));
		}

		/// <summary>
		/// Let user add TextBox like control type name
		/// </summary>
		/// <param name="stringType">TextBox like control type name</param>
		public void AddTextBoxLikeControl(string stringType)
		{
			_TextBoxLikeControl.Add(stringType);
		}

		/// <summary>
		/// Let users provide their own print function for specific control type
		/// </summary>
		/// <param name="stringType">Control type name</param>
		/// <param name="printFunction">function (must match with FormPrinting.ControlPrinting delegate)</param>
		public void AddDelegateToPrintControl(string stringType, ControlPrinting printFunction)
		{
			_DelegateforControls d = new _DelegateforControls();
			d.typ = stringType;
			d.PrintFunction = printFunction;
			_DelegatesforControls.Add(d);
		}
	#endregion

	#region  "Private data"
		//		private Font _printFont;
		private Pen _Pen;
		private Brush _Brush;
		private System.Windows.Forms.Control _f;
		private ArrayList _TextBoxLikeControl;
		private System.Single _xform;
		private ArrayList _DelegatesforControls;
		private MultiPageManagement _MultiPage;
		private System.Text.StringBuilder _traceLog;
		private int _indent;
        
		private class _DelegateforControls
		{
			public string typ;
			public ControlPrinting PrintFunction;
		}
	#endregion

	#region "Managing PrintDocument or TIF object"
		/// <summary>
		/// Launch printing. Calculate start position and orientation
		/// </summary>
		public void Print()
		{
			try
			{
				PrintDocument pd = new PrintDocument();
				InitPrinting(ref pd);
				pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
				pd.DocumentName = _f.Text;
				if (PrintPreview)
				{
					PrintPreviewDialog pp =  new PrintPreviewDialog();
					pp.Document = pd;
					pp.WindowState = FormWindowState.Maximized;
					pp.ShowDialog();
				}
				else
				{
					pd.Print();
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString());
			}
		}

		public void PrintToTifFile(string fileName)
		{
			try
			{
				// Compute bitmap propertiy about same as default printer
				PrintDocument pd = new PrintDocument();
				InitPrinting(ref pd);
				System.Drawing.Bitmap bitmapAllPages, bitmapAdditionnalPage;
				bitmapAllPages = new Bitmap(pd.DefaultPageSettings.Bounds.Width, pd.DefaultPageSettings.Bounds.Height);
				bitmapAdditionnalPage = new Bitmap(pd.DefaultPageSettings.Bounds.Width, pd.DefaultPageSettings.Bounds.Height);
				Graphics g;

				//Prepare parameters to save multiframe image
				System.Drawing.Imaging.EncoderParameters eps;
				eps = new System.Drawing.Imaging.EncoderParameters();
				bool firstPage = true;

				// Print pages
				do
				{
					if (firstPage)
						g = Graphics.FromImage(bitmapAllPages);
					else
						g = Graphics.FromImage(bitmapAdditionnalPage);
					g.Clear(System.Drawing.Color.White); 
					_MultiPage.NewPage(g);
					Single extendedHeight;
					Single y;

					y = 0;
					extendedHeight = 0;
					bool scanForChildControls;
					if (DelegatePrintingReportTitle == null)
						PrintReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls);
					else
						DelegatePrintingReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls);
					y += extendedHeight;

					// Print each control on the form
					Single globalExtendedHeight;
					PrintControls(_f, _MultiPage, _xform, y, out globalExtendedHeight);

					if(firstPage)
					{
						//Create the parameter and choose multi-frame
						eps.Param[0]=new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.MultiFrame);
						//Get the correct encoder from the list of available encoders
						ImageCodecInfo[] infos=ImageCodecInfo.GetImageEncoders();
						int n=0;
						while(infos[n].MimeType!="image/tiff")
							n++;
						//save the first page
						bitmapAllPages.Save(fileName + ".tif",infos[n],eps);
					}
					else
					{
						//Create the parameter and choose FrameDimensionPage
						eps.Param[0]=new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.FrameDimensionPage);
						//save the first page
						bitmapAllPages.SaveAdd(bitmapAdditionnalPage,eps);
					}
					firstPage = false;
				} while (!_MultiPage.LastPage());

				// Flush pages to file
				eps.Param[0]=new EncoderParameter(Encoder.SaveFlag,(long)EncoderValue.Flush);
				bitmapAllPages.SaveAdd(eps);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString());
			}
		}

		public string GetTrace()
		{
			return _traceLog.ToString();
		}

		private void InitPrinting(ref PrintDocument pd)
		{

			_traceLog = new System.Text.StringBuilder();
			_indent = 0;
			// Calculate Form position for printing
			switch (Orientation)
			{
				case OrientationENum.Automatic:
					if (_f.Size.Width > (pd.DefaultPageSettings.Bounds.Width - pd.DefaultPageSettings.Margins.Right - pd.DefaultPageSettings.Margins.Left))
						pd.DefaultPageSettings.Landscape = true;
					break;
				case OrientationENum.Lanscape:
					pd.DefaultPageSettings.Landscape = true;
					break;
				case OrientationENum.Portrait:
					pd.DefaultPageSettings.Landscape = false;
					break;
			}

			// Set page area
			Single pageTop = pd.DefaultPageSettings.Margins.Top;
			Single pageBottom = pd.DefaultPageSettings.Bounds.Height - pd.DefaultPageSettings.Margins.Bottom;
			Single pageLeft = pd.DefaultPageSettings.Margins.Left;
			Single pageRight = pd.DefaultPageSettings.Bounds.Width - pd.DefaultPageSettings.Margins.Right;
			if (TopMargin != 0)
				pageTop = TopMargin;
			if (BottomMargin != 0)
				pageTop = BottomMargin;

			// Calculate left position of print
			switch (this.HAlignment)
			{
				case HorizontalAlignment.Left: 
					_xform = pageLeft;
					break;
				case HorizontalAlignment.Center: 
					_xform = (pd.DefaultPageSettings.Bounds.Width - _f.Size.Width) / 2;
					break;
				case HorizontalAlignment.Right: 
					_xform = pageRight - _f.Size.Width;
					break;
			}

			_MultiPage = new MultiPageManagement(pageTop, pageBottom, pageLeft, pageRight, _f.Font, PageNumbering, PageNumberingFormat);
		}

		/// <summary>
		/// Event handler called by the print document engine. Called for each pages
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="ev"></param>
		private void pd_PrintPage(object sender, PrintPageEventArgs ev)
		{
			_MultiPage.NewPage(ev.Graphics);
			Single extendedHeight;
			Single y;

			y = 0;
			extendedHeight = 0;
			bool scanForChildControls;
			if (DelegatePrintingReportTitle == null)
				PrintReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls);
			else
				DelegatePrintingReportTitle(_f, ParentControlPrinting.BeforeChilds , _MultiPage, _xform, y, ref extendedHeight, out scanForChildControls);
			y += extendedHeight;

			// Print each control on the form
			Single globalExtendedHeight;
			PrintControls(_f, _MultiPage, _xform, y, out globalExtendedHeight);

			if (_MultiPage.LastPage())
			{
				ev.HasMorePages = false;
				_MultiPage.ResetPage();
			}
			else
				ev.HasMorePages = true;
		}

		public void PrintReportTitle(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;
			Font printFont = new Font(c.Font.Name, (Single) (c.Font.Size * 1.3), FontStyle.Bold);
			float fontHeight =  mp.FontHeight(printFont);
			Pen pen = new Pen(Color.Black, 2);
			extendedHeight = fontHeight + 3 + pen.Width + 1;

			mp.BeginPrintUnit(y, extendedHeight);
			mp.DrawString(c.Text, printFont, Brushes.Black, x, y, c.Width, fontHeight);
			y += fontHeight + 3;
			mp.DrawLines(pen, x, y, x + c.Size.Width, y);
			mp.EndPrintUnit();
		}

	#endregion

	#region "Recursive printing of controls"
		/// <summary>
		/// Print child controls of a "parent" control.
		/// Controls are printed from top to bottom.
		/// This is the function that calculate position of each control depending of the extension of child controls
		/// </summary>
		/// <param name="c">"parent" control</param>
		/// <param name="mp">printing page object</param>
		/// <param name="x">X position of "parent" control</param>
		/// <param name="y">Y position of "parent" control</param>
		/// <param name="globalExtendedHeight">necessary height grow of "parent" control to fit with combination of child control growing</param>
		public void PrintControls(System.Windows.Forms.Control c,
			MultiPageManagement mp,
			Single x, Single y,
			out Single globalExtendedHeight)
		{
			int nbCtrl = c.Controls.Count;
			Single[] yPos = new Single[nbCtrl];
			System.Windows.Forms.Control[] controls = new System.Windows.Forms.Control[nbCtrl];

			//Do a list of child controls
			for (int i = 0; i < nbCtrl; i++)
			{
				controls[i] = c.Controls[i];
				yPos[i] = c.Controls[i].Location.Y;
			}

			//Sort them by vertical position
			System.Array.Sort(yPos, controls);

			//Print them from top to bottom
			globalExtendedHeight = 0;
			//Single globalextendedYPos = 0;
			System.Collections.ArrayList extendedYPos = new System.Collections.ArrayList();

			// *****************************************************************
			//		This loop over child controls calculate position of them.
			// Algorithm take care of controls that expand besides and above.
			// It keep an arraylist of original and printed (after expansion) bottom
			// position of expanded control.
			// So control is push down if it was originally below expanded controls
			// *****************************************************************
			for (int i = 0; i < nbCtrl; i++)
			{
				// Set y position of control depending of extension of controls above him
				Single pushDownHeight = 0;
				foreach (Element e in extendedYPos)
					if (controls[i].Location.Y >= e.originalBottom) //completely under it
					{
						if (e.totalPushDown > pushDownHeight) 
							pushDownHeight = e.totalPushDown; 
					}
				Single cp = controls[i].Location.Y + pushDownHeight;

				Single extendedHeight;
				PrintControl(controls[i], mp, x + controls[i].Location.X, y + cp, out extendedHeight);
				if (extendedHeight > 0)
				{
					//Keep extention with y position
					Element e = new Element();
					e.originalBottom = controls[i].Location.Y + controls[i].Height;
					e.printedBottom = cp + controls[i].Height + extendedHeight;
					extendedYPos.Add(e);
				}
			}
			// same computation for bottom of container control. Its bottom line is
			// below all child controls. So it is extended the same as the most pushed
			// child control.
			globalExtendedHeight = 0;
			foreach (Element e in extendedYPos)
				if (e.totalPushDown > globalExtendedHeight) 
					globalExtendedHeight = e.totalPushDown; 

		}
		private class Element
		{
			public Single originalBottom;
			public Single printedBottom;
			public  Single totalPushDown
			{get {return printedBottom - originalBottom;} }
		}

		/// <summary>
		/// This sub simply use recursivity to print child controls and print
		/// the parent control (height may grow depending of child controls).
		/// Extension is push up to the previous parent.
		/// </summary>
		/// <param name="c"></param>
		/// <param name="mp"></param>
		/// <param name="x"></param>
		/// <param name="y"></param>
		/// <param name="extendedHeight"></param>
		public void PrintControl(System.Windows.Forms.Control c,
			MultiPageManagement mp,
			Single x, Single y,
			out Single extendedHeight)
		{
			extendedHeight = 0;
			if (c.Visible == true)
			{
				bool scanForChildControls;
				try
				{
					// Print my header
					PrintOneControl(c, ParentControlPrinting.BeforeChilds, mp, x, y, ref extendedHeight, out scanForChildControls);

					// Print Contained controls
					if (scanForChildControls)
					{
						y += extendedHeight;

						_indent += 1;
						Single ChildControlsExtendedHeight;
						PrintControls(c, mp, x, y, out ChildControlsExtendedHeight); 
						_indent -= 1;

						// Print my bottom (habitually a frame arround child controls)
						PrintOneControl(c, ParentControlPrinting.AfterChilds, mp, x, y, ref ChildControlsExtendedHeight, out scanForChildControls);
						extendedHeight += ChildControlsExtendedHeight;
					}
				}
				catch (Exception ex)
				{
					MessageBox.Show("Error printing control of type " + 
						c.GetType().ToString()+
						System.Environment.NewLine + 
						System.Environment.NewLine + ex.ToString());
				}
			}
		}

		/// <summary>
		/// Print a control (not is children). Call the print function depending of the type of the control
		/// </summary>
		/// <param name="c"></param>
		/// <param name="mp"></param>
		/// <param name="x"></param>
		/// <param name="y"></param>
		/// <param name="extendedHeight"></param>
		public void PrintOneControl(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			// Silver color if disable
			if (c.Enabled || !DisabledControlsInGray)
			{
				_Pen = new Pen(Color.Black);
				_Brush = Brushes.Black;
			}
			else
			{
				_Pen = new Pen(Color.Silver);
				_Brush = Brushes.Silver;
			}

			ScanForChildControls = true;
			string s = c.GetType().ToString();
			bool founded = false;
			//First check if it's a text box like control
			if (!founded)
				foreach (string sType in _TextBoxLikeControl)
					if (s.IndexOf(sType) >= 0)
					{
						Single h;
						h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size));
						extendedHeight = mp.BeginPrintUnit(y, h);
						PrintText(c, mp, x, y, TextBoxBoxed, false, TextBoxBoxed, HorizontalAlignment.Left);
						mp.EndPrintUnit();
						founded = true;
						ScanForChildControls = false;
						break;
					}

			//Process other type of control, beginning at the end of the list (use last add for a type)
			if (!founded)
				for (int i = _DelegatesforControls.Count-1; i>=0; i--)  // from end to the beginning
				{
					_DelegateforControls d = (_DelegateforControls) _DelegatesforControls[i];
					if (s.EndsWith(d.typ))
					{
						d.PrintFunction(c, typePrint, mp, x, y, ref extendedHeight, out ScanForChildControls);
						break;
					}
				}
			_traceLog.Append(_indent.ToString() + " - " + typePrint.ToString() + "  " + s + " (" + c.Text + ":" + c.Name + ")  X=" + x.ToString() +  "   Y=" + y.ToString() + "   H=" + c.Height.ToString() + "   + " + extendedHeight.ToString()+ System.Environment.NewLine);
		}
	#endregion

	#region "Text printing"
		/// <summary>
		/// Print a single line text for many controls. Do some formatting
		/// </summary>
		/// <param name="c">Control to print (must have these properties :font, text, width and height)</param>
		/// <param name="mp">Graphics object (printed page)</param>
		/// <param name="x">X position</param>
		/// <param name="y">Y position</param>
		/// <param name="tbBoxed">Draw a box arround text</param>
		/// <param name="inBold">use bold font</param>
		/// <param name="verticalCentering">Adjust vertical to obtain precise alignment from different type of control</param>
		/// <param name="hAlignment">Horizontal alignment of text in control print area</param>
		public void PrintText(System.Windows.Forms.Control c, 
							MultiPageManagement mp,
							Single x, Single y,
							bool tbBoxed, bool inBold, bool verticalCentering, 
							HorizontalAlignment hAlignment)
		{
			Single yAdjusted = y;
			//Box
			if (tbBoxed)
				mp.DrawRectangle(_Pen, x, y, c.Width, c.Height);

			//Text
			Font printFont;
			if (inBold)
				printFont = new Font(c.Font.Name, c.Font.Size-1, FontStyle.Bold);
			else
				printFont = new Font(c.Font.Name, c.Font.Size-1);

			if (verticalCentering)
			{
				Single fontHeight = printFont.GetHeight(mp.Graphics());
				Single deltaHeight = (c.Height - fontHeight) / 2;
				yAdjusted += deltaHeight;
			}
			else
				yAdjusted += 2;
	
			mp.DrawString(c.Text, printFont, _Brush, x, yAdjusted, c.Width, c.Height, BuildFormat(hAlignment));
		}

		public StringFormat BuildFormat(HorizontalAlignment hAlignment)
		{
			StringFormat drawFormat = new StringFormat();
			switch (hAlignment)
			{
				case HorizontalAlignment.Left:
					drawFormat.Alignment = StringAlignment.Near;
					break;
				case HorizontalAlignment.Center:
					drawFormat.Alignment = StringAlignment.Center;
					break;
				case HorizontalAlignment.Right:
					drawFormat.Alignment = StringAlignment.Far;
					break;
			}
			return drawFormat;
		}

		public string TrimBlankLines(string s)
		{
			if (s == null)
				return s;
			else
			{
				for (int i = s.Length; i==1; i--)
					if ((s[i].ToString() != Keys.Enter.ToString()) && (s[i].ToString() != Keys.LineFeed.ToString())  && (s[i].ToString() != " "))
						return s.Substring(0, i);
				return s;
			}
		}
	#endregion

	#region "Controls printing"
		/// <summary>
		/// Print single line or multi lines TextBox.
		/// </summary>
		public void PrintTextBox(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;

			TextBox tb = (System.Windows.Forms.TextBox) c;
			Single h = mp.FontHeight(new Font(tb.Font.Name, tb.Font.Size));
			if (!tb.Multiline)
			{
				extendedHeight = mp.BeginPrintUnit(y, h);
				PrintText(c, mp, x, y, TextBoxBoxed, tb.Font.Bold, TextBoxBoxed, tb.TextAlign);
				mp.EndPrintUnit();
			}
			else  //multiline
			{
				// cut text into lines that fit in printed textBox width
				// Define an area of one line height and call MeasureString on it
				// This method return charactersFitted for the line
				ArrayList lines = new ArrayList();
				System.Drawing.Graphics g = mp.Graphics();
				SizeF areaForOneLineOfText = new SizeF();
				areaForOneLineOfText.Height = h;
				areaForOneLineOfText.Width = tb.Width;
				int charactersFitted;
				int linesFilled;
				int separatorCharPos;
				Font printFont = new Font(tb.Font.Name, tb.Font.Size);

				int pos = 0;
				do
				{
					g.MeasureString(tb.Text.Substring(pos),
									printFont,
									areaForOneLineOfText,
									new StringFormat(), 
									out charactersFitted,
									out	linesFilled);
					// this method with one line cut the last word....
					// So, I have to go bak in the string to find a separator
					// Happyly, MeasureString count separator character in charactersFitted
					// For example, return "this is the first line " with space at the end
					// even if there is not room for last space
					separatorCharPos = charactersFitted;
					if (charactersFitted < tb.Text.Substring(pos).Length) //le restant n'entre pas au complet sur la ligne
					{
						do
						{ separatorCharPos --; }
						while ((separatorCharPos > pos) && !System.Char.IsSeparator(tb.Text, pos + separatorCharPos));
						if (separatorCharPos == pos)   // no separator
							separatorCharPos = charactersFitted;
						else
							separatorCharPos ++;
					}
					lines.Add(tb.Text.Substring(pos, separatorCharPos));
					pos += separatorCharPos;
				}
				while ((pos < tb.Text.Length) && (charactersFitted > 0));

				// Print lines one by one
				Single yItem = y;
				Single extraHeight;
				Single extraHeightFirstLine = 0;	//Remenber if first line is pull down
				for (int i=0; i < lines.Count; i++)
				{
					extraHeight = mp.BeginPrintUnit(yItem, h);   //Space required for tab page caption
					if (i == 0)
						extraHeightFirstLine = extraHeight;
					mp.DrawString((string) lines[i], printFont, _Brush, x, yItem, tb.Width, h);
					mp.EndPrintUnit();
					yItem += h + extraHeight;
				}

				if ((yItem - y) > tb.Height)
					extendedHeight = (yItem - y) - tb.Height;

				if (TextBoxBoxed)
				{
					_Pen = new Pen(Color.Gray);
					//Draw a rectangle arround list box. Start downer if first line pulled down
					mp.DrawFrame(_Pen, x, y + extraHeightFirstLine, tb.Width, tb.Height + extendedHeight - extraHeightFirstLine);
				}
			}
		}

        public void PrintButton(System.Windows.Forms.Control c,
        ParentControlPrinting typePrint,
        MultiPageManagement mp,
        Single x, Single y,
        ref Single extendedHeight, out bool ScanForChildControls)
        {
            ScanForChildControls = false;
            // Convert ContentAlignment (property of labels) to HorizontalAlignment (Left, center, Right)
            HorizontalAlignment ha;
            string ss = c.Text;

            ContentAlignment ha2 = ((Button)c).TextAlign;
            switch (ha2)
            {
                case ContentAlignment.BottomLeft:
                    ha = HorizontalAlignment.Left;
                    break;
                case ContentAlignment.TopLeft:
                    ha = HorizontalAlignment.Left;
                    break;
                case ContentAlignment.MiddleLeft:
                    ha = HorizontalAlignment.Left;
                    break;

                case ContentAlignment.BottomCenter:
                    ha = HorizontalAlignment.Center;
                    break;
                case ContentAlignment.TopCenter:
                    ha = HorizontalAlignment.Center;
                    break;
                case ContentAlignment.MiddleCenter:
                    ha = HorizontalAlignment.Center;
                    break;

                case ContentAlignment.BottomRight:
                    ha = HorizontalAlignment.Right;
                    break;
                case ContentAlignment.TopRight:
                    ha = HorizontalAlignment.Right;
                    break;
                case ContentAlignment.MiddleRight:
                    ha = HorizontalAlignment.Right;
                    break;
                default:
                    ha = HorizontalAlignment.Left;
                    break;
            }

            Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size - 5));
            if (c.Height > h)
                h = c.Height;
            extendedHeight = mp.BeginPrintUnit(y, h);
            PrintText(c, mp, x, y, false, LabelInBold, false, ha);
            mp.EndPrintUnit();
        }

		public void PrintLabel(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;
			// Convert ContentAlignment (property of labels) to HorizontalAlignment (Left, center, Right)
			HorizontalAlignment ha ;
			string ss = c.Text;
            
			ContentAlignment ha2 = ((Label) c).TextAlign;
			switch (ha2)
			{
				case ContentAlignment.BottomLeft:
					ha = HorizontalAlignment.Left;
					break;
				case ContentAlignment.TopLeft:
					ha = HorizontalAlignment.Left;
					break;
				case ContentAlignment.MiddleLeft:
					ha = HorizontalAlignment.Left;		
					break;

				case ContentAlignment.BottomCenter:
					ha = HorizontalAlignment.Center;
					break;
				case ContentAlignment.TopCenter:
					ha = HorizontalAlignment.Center;
					break;
				case ContentAlignment.MiddleCenter:
					ha = HorizontalAlignment.Center;
					break;

				case ContentAlignment.BottomRight:
					ha = HorizontalAlignment.Right;
					break;
				case ContentAlignment.TopRight:
					ha = HorizontalAlignment.Right;
					break;
				case ContentAlignment.MiddleRight:
					ha = HorizontalAlignment.Right;
					break;
				default:
					ha = HorizontalAlignment.Left;		
					break;
			}
            
			Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size- 5));
			if (c.Height > h)
				h = c.Height;
			extendedHeight = mp.BeginPrintUnit(y, h);
			PrintText(c, mp, x, y, false, LabelInBold, false, ha);
			mp.EndPrintUnit();
		}

		public void PrintCheckBox(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;
			Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size));
			extendedHeight = mp.BeginPrintUnit(y, h);

			mp.DrawRectangle(_Pen, x, y, h, h);
			if ( ((CheckBox) c).Checked )
			{
				Single d = 3;
				mp.DrawLines(_Pen, x + d, y + d, x + h - d, y + h - d);
				PointF[] points2 = new PointF[] {new PointF(x + h - d, y + d), new PointF(x + d, y + h - d)};
				mp.DrawLines(_Pen, x + h - d, y + d, x + d, y + h - d);
			}
			PrintText(c, mp, (float) (x + (h * 1.4)), (float) y - 2, false, false, false, HorizontalAlignment.Left);
			mp.EndPrintUnit();
		}

		public void PrintRadioButton(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;
			Single h = mp.FontHeight(new Font(c.Font.Name, c.Font.Size));
			extendedHeight = mp.BeginPrintUnit(y, h);
			mp.DrawEllipse(_Pen, x, y, h, h);
			if ( ((RadioButton) c).Checked)
			{
				Single d = 3;
				mp.FillEllipse(_Brush, x + d, y + d, h - d - d, h - d - d);
			}
			PrintText(c, mp, (float) (x + (h * 1.4)), y - 2, false, false, false, HorizontalAlignment.Left);
			mp.EndPrintUnit();
		}

		public void PrintPanel(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = true;
			if (typePrint == ParentControlPrinting.AfterChilds)
				if ( ((System.Windows.Forms.Panel) c).BorderStyle != BorderStyle.None)
				{
					if (((System.Windows.Forms.Panel) c).BorderStyle == BorderStyle.Fixed3D)
						_Pen = new Pen(Color.Silver);
					// if height less than 10, just print an horizontal line
					if ((c.Height < 10) && (c.Controls.Count == 0))
					{
						extendedHeight += mp.BeginPrintUnit(y, 1);
						mp.DrawLines(_Pen, x, y, x + c.Width, y);
						mp.EndPrintUnit();
					}
					else
						mp.DrawFrame(_Pen, x, y, c.Width, c.Height + extendedHeight);
				}
		}

		public void PrintGroupBox(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = true;
			Font printFont = new Font(c.Font.Name, c.Font.Size);
			Single h = mp.FontHeight(printFont);
			_Pen = new Pen(Color.Silver);
			switch (typePrint)
			{
				case ParentControlPrinting.BeforeChilds :
					// if height less than 10, just print an horizontal line
					if ((c.Height < 10) && (c.Controls.Count == 0))
					{
						extendedHeight += mp.BeginPrintUnit(y, 1);
						mp.DrawLines(_Pen, x, y, x + c.Width, y);
						mp.EndPrintUnit();
					}
					else
					{
						Single extraHeight = mp.BeginPrintUnit(y, h);   //Space required for group caption
						//PrintText(c, mp, x + h, y, false, true, false, HorizontalAlignment.Left);
						mp.DrawString(c.Text, printFont, Brushes.Black, x + h, y, c.Width - h - h, h);
						mp.EndPrintUnit();
						extendedHeight += extraHeight;
					};
					break;
				case ParentControlPrinting.AfterChilds :
					mp.DrawFrame(_Pen, x, y, c.Width, c.Height + extendedHeight);
					break;
			}
		}

		public void PrintTabControl(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = true;
			System.Windows.Forms.TabControl tc = (TabControl) c;
			_Pen = new Pen(Color.Gray);
			switch (typePrint)
			{
				case ParentControlPrinting.BeforeChilds :
					//Nom du TabPage
					Single extraHeight = mp.BeginPrintUnit(y, tc.ItemSize.Height);   //Space required for tab page caption
					System.Windows.Forms.TabPage tp = tc.SelectedTab;
					Font printFont = new Font(tp.Font.Name, tp.Font.Size, FontStyle.Bold);
					Single h = mp.FontHeight(printFont);
					if (h > tc.ItemSize.Height)
						h = tc.ItemSize.Height;
					mp.DrawString(tp.Text, printFont, Brushes.Black, x, y + (tc.ItemSize.Height - h) / 2, tp.Width, h);
					mp.DrawLines(_Pen, x, y + tc.ItemSize.Height, x + tc.Width, y + tc.ItemSize.Height);
					mp.EndPrintUnit();
					extendedHeight += extraHeight;
					break;
				case ParentControlPrinting.AfterChilds :
					if (TabControlBoxed)
						mp.DrawFrame(_Pen, x, y, c.Width, c.Height + extendedHeight);
					break;
			}
		}

		public void PrintPictureBox(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;
			extendedHeight = mp.BeginPrintUnit(y, c.Height);
			PictureBox pic = (PictureBox) c;
			mp.DrawImage(pic.Image, x, y, c.Width, c.Height);
			mp.EndPrintUnit();
		}

		public void PrintListBox(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;
			ListBox lb = (ListBox) c;
			Single yItem = y;
			Single extraHeight;
			Single extraHeightFirstLine = 0;	//Remenber if first line is pull down
			Font printFont = new Font(lb.Font.Name, lb.Font.Size, FontStyle.Bold);

			int oldPos = lb.SelectedIndex; //save position
			for (int i = 0; i < lb.Items.Count; i++)
			{
				extraHeight = mp.BeginPrintUnit(yItem, lb.ItemHeight);   //Space required for tab page caption
				if (i == 0)
					extraHeightFirstLine = extraHeight;
				lb.SelectedIndex = i; // set position to obtain Text of current item
				mp.DrawString(lb.Text, printFont, _Brush, x, yItem, lb.Width, lb.ItemHeight);
				mp.EndPrintUnit();
				yItem += lb.ItemHeight + extraHeight;
			}
			lb.SelectedIndex = oldPos; //restore position

			if ((yItem - y) > lb.Height)
				extendedHeight = (yItem - y) - lb.Height;

			_Pen = new Pen(Color.Gray);
			//Draw a rectangle arround list box. Start downer if first line pulled down
			mp.DrawFrame(_Pen, x, y + extraHeightFirstLine, c.Width, c.Height + extendedHeight - extraHeightFirstLine);
		}

		public void PrintDataGrid(System.Windows.Forms.Control c,
			ParentControlPrinting typePrint, 
			MultiPageManagement mp, 
			Single x, Single y,
			ref Single extendedHeight, out bool ScanForChildControls)
		{
			ScanForChildControls = false;

			DataGrid dg = (DataGrid) c;
			Single extraHeight = 0;
			Single extraHeightHeaderLine = 0;
			Font printFont = new Font(dg.Font.Name, dg.Font.Size, FontStyle.Bold);
			Single h = mp.FontHeight(printFont);

			// Column header
			DataGridTableStyle myGridTableStyle;
			if (dg.TableStyles.Count == 0)
			{
				myGridTableStyle = new DataGridTableStyle();
				dg.TableStyles.Add(myGridTableStyle);
			}

			// Header of each column
			Single xPos = x;
			Single yPos = y;
			Single w;
			extraHeightHeaderLine = mp.BeginPrintUnit(yPos, h+1);  //Space required for header text
			for (int i = 0; i < dg.TableStyles[0].GridColumnStyles.Count; i++)
			{
				string caption = dg.TableStyles[0].GridColumnStyles[i].HeaderText;
				w = dg.TableStyles[0].GridColumnStyles[i].Width;
				if (xPos+w > x + dg.Width)
					w = x + dg.Width - xPos;
				if (xPos < x + dg.Width)
					mp.DrawString(caption, printFont, _Brush, xPos, yPos, w, h);
				if (i == 0)  // Draw horizontal line below header
					mp.DrawLines(_Pen, x, yPos+h, x+dg.Width, yPos+h);
				xPos += w;
			}
			mp.EndPrintUnit();
			yPos += h + 1 + extraHeightHeaderLine;

			// Get dataTable displayed in DataGrid
			// This function only support DataGrid with DataTable as DataSource
			// This is the only case I code to obtain data in DataGrid
			DataTable dt = null;
			if (dg.DataSource is System.Data.DataTable)
				dt = (DataTable) dg.DataSource;
			else
				if ((dg.DataSource is System.Data.DataSet) && (dg.DataMember != null))
				{
					DataSet ds = (DataSet) dg.DataSource;
					if (ds.Tables.Contains(dg.DataMember))
						dt = ds.Tables[dg.DataMember];
				}

			// Loop on DataRow, with embed loop on columns
			if (dt != null)
				foreach (DataRow dr in dt.Rows)
				{
					extraHeight = mp.BeginPrintUnit(yPos, h);  //Space required for header text
					xPos = x;
					for (int i = 0; i < dg.TableStyles[0].GridColumnStyles.Count; i++)
					{
						string caption = dr[i].ToString();
						w = dg.TableStyles[0].GridColumnStyles[i].Width;
						if (xPos+w > x + dg.Width)
							w = x + dg.Width - xPos;
						if (xPos < x + dg.Width)
							mp.DrawString(caption, printFont, _Brush, xPos, yPos, w, h);
						xPos += w;
					};
					mp.EndPrintUnit();
					yPos += h + extraHeight;
				}

			// Draw horizontal line at the bottom of DataGrid
			if (yPos < y + dg.Height + extraHeightHeaderLine)
				yPos = y + dg.Height + extraHeightHeaderLine;
			mp.BeginPrintUnit(yPos, 1);
			mp.DrawLines(_Pen, x, yPos, x+dg.Width, yPos);
			mp.EndPrintUnit();
			
			// Finally, Compute extendedHeight
			if ((yPos - y) > dg.Height)
				extendedHeight = (yPos - y) - dg.Height;
		}

//		public void PrintFlexGrid(System.Windows.Forms.Control c,
//			ParentControlPrinting typePrint, 
//			MultiPageManagement mp, 
//			Single x, Single y,
//			ref Single extendedHeight, out bool ScanForChildControls)
//		{
//			ScanForChildControls = false;
		//			C1.Win.C1FlexGrid.C1FlexGrid g = (C1.Win.C1FlexGrid.C1FlexGrid) c;
		//
		//			// print rows and column header (row[0])
		//			RectangleF r = new RectangleF();
		//			PointF[] points;
		//			r.Y = y; //+ r.Height + _Pen.Width ;
		//			r.Height = g.Font.GetHeight(ev.Graphics);
		//
		//			for (int i = 0; i < g.Rows.Count; i++) // each row
		//			{
		//				r.X = x;
		//				for (int j = 0; j<g.Cols.Count; j++) // each column
		//					if ((g.Cols[j].Visible) && (r.X < x + g.Width)) //if not out of grid
		//					{
		//						r.Width = g.Cols[j].Width;
		//						if ((r.X + r.Width) > (x + g.Width)) //overtaking
		//							r.Width = (x + g.Width) - r.X;
		//						ev.Graphics.DrawString(g.GetDataDisplay(i,j), g.Font, _Brush, r, new StringFormat());
		//						r.X += r.Width;
		//					}
		//				r.Y += r.Height;
		//				if (i == 0) //Columns header, Add an horizontal line below
		//				{
		//					r.Y += 1;
		//					points = new PointF[] {new PointF(x, r.Y), new PointF(x + g.Width, r.Y)};
		//					ev.Graphics.DrawLines(_Pen, points);
		//					r.Y += _Pen.Width ;
		//				}
		//			}
		//
		//			// Add a bottom line
		//			points = new PointF[] {new PointF(x, r.Y), new PointF(x + g.Width, r.Y)};
		//			ev.Graphics.DrawLines(_Pen, points);
		//			r.Y += _Pen.Width ;
		//
		//			// Compute extendedHeight
		//			if (r.Y > y + g.Height)
		//				extendedHeight = r.Y - (y + g.Height);
//		}
		
//		StringFormat _StringFormatFromFlexGridAlign(C1.Win.C1FlexGrid.TextAlignEnum fg)
//		{
//			StringFormat sf = new StringFormat();
//			string s = fg.ToString().ToUpper();
//			if (s.IndexOf("LEFT") == 0)
//				sf.Alignment = System.Drawing.StringAlignment.Near; 
//			if (s.IndexOf("RIGHT") == 0)
//				sf.Alignment = System.Drawing.StringAlignment.Far;
//			if (s.IndexOf("CENTER") == 0)
//				sf.Alignment = System.Drawing.StringAlignment.Center; 
//			return sf;
//		}


	#endregion

	#region "Multi page class"
		public class MultiPageManagement 
		{
			private bool _PageOverflow;
			private Single _realPageTop, _realPageHeight, _UsablePageHeight;
			private Single _realPageLeft, _realPageRight;
			private Single _CurrentPageTop, _CurrentPageBottom;
			private int _PageNumber = 0;
			//private PrintPageEventArgs _Ev;
			private Graphics _G;
			private bool _PrintUnit;
			private bool _PrintInCurrentPage;
			private Single _PrintUnitPullDown;
			private bool _pageNumbering;
			private Font _FontForPageNumering;
			private string _PageNumberingFormat;

			public System.Drawing.Graphics Graphics()
			{
				return _G;
			}

			// Constructor
			public MultiPageManagement(Single pageTop, Single pageBottom, Single pageLeft, Single pageRight, Font formFont, bool pageNumbering, string pageNumberingFormat)
			{
				_realPageTop = pageTop;
				_realPageHeight = pageBottom - pageTop;
				_realPageLeft = pageLeft;
				_realPageRight = pageRight;
				_pageNumbering = pageNumbering;
				if (_pageNumbering)
				{
					_PageNumberingFormat = pageNumberingFormat;
					_FontForPageNumering = new Font(formFont.Name, (Single) (formFont.Size * 0.8));
				}
			}

			/// <summary>
			/// Check if items printed below current page
			/// </summary>
			/// <returns>Return true if there is need for another page</returns>
			public bool LastPage()
			{
				return (! _PageOverflow);
			}

			/// <summary>
			/// Change page. Reset page properties
			/// </summary>
			/// <param name="g">Graphics object</param>
			public void NewPage(Graphics g)
			{
				_G = g;
				_PageNumber += 1;
				_UsablePageHeight = _realPageHeight;
				if (_pageNumbering)
				{
					Single fontHeightForPageNumbering =  FontHeight(_FontForPageNumering);
					_UsablePageHeight -= (Single) (fontHeightForPageNumbering * 1.5);
					// Compute rectangular space for page number
					RectangleF _recForPageNumbering = new RectangleF();
					_recForPageNumbering.X = _realPageLeft;
					_recForPageNumbering.Y = _realPageTop + _realPageHeight - fontHeightForPageNumbering;
					_recForPageNumbering.Width = _realPageRight - _realPageLeft;
					_recForPageNumbering.Height = fontHeightForPageNumbering;
					// impression
					StringFormat drawFormat = new StringFormat();
					drawFormat.Alignment = StringAlignment.Far;
					_G.DrawString(String.Format(_PageNumberingFormat, _PageNumber), _FontForPageNumering, Brushes.Black, _recForPageNumbering, drawFormat);
				}
				_CurrentPageTop = _UsablePageHeight * (_PageNumber - 1);
				_CurrentPageBottom = _CurrentPageTop + _UsablePageHeight;
				_PageOverflow = false;
			}

			public void ResetPage()
			{
				_PageNumber = 0;
			}

			public Single BeginPrintUnit(Single y, Single neededHeight)
			{
				if (neededHeight > _UsablePageHeight)
					throw new Exception("Needed height cannot exceed 1 page. Page height = " + _UsablePageHeight);
				_PrintUnit = true;


				// Verify if unit goes accross a page break
				// if it's the case, calculate vertical push down height to place the
				// top of unit just below page break
				Single pageBreakPos;
				Single printingPos = y;
				for (pageBreakPos = _UsablePageHeight; pageBreakPos < (y + neededHeight); pageBreakPos += _UsablePageHeight)
					if( (y <= pageBreakPos) && ((y + neededHeight - 1) > pageBreakPos) ) //Accross
						printingPos = pageBreakPos;

				_PrintUnitPullDown = printingPos - y;

				// test if unit is in current page else if another page is needed
				_PrintInCurrentPage = false;
				if (printingPos + neededHeight - 1 > _CurrentPageBottom)
					_PageOverflow = true;
				else
					if (printingPos >= _CurrentPageTop)
						_PrintInCurrentPage = true;

				return _PrintUnitPullDown;
			}

			private Single _ConvertToPage(Single y)
			{
				Single newY = y - _CurrentPageTop + _realPageTop;
				if (_PrintUnit)
					return newY += _PrintUnitPullDown;
				return newY;
			}

			public void EndPrintUnit()
			{
				_PrintUnit = false;
			}

			private bool PrintUnitIsInCurrentPage()
			{
				if (!_PrintUnit)
					throw new Exception("Must be in a print unit to print");
				return _PrintInCurrentPage;
			}

			public Single FontHeight(Font font)
			{
				return font.GetHeight(_G);
			}

			public void DrawLines(Pen pen, Single x1, Single y1, Single x2, Single y2)
			{
				if (PrintUnitIsInCurrentPage())
				{
					Single y1page = _ConvertToPage(y1);
					Single y2page = _ConvertToPage(y2);
					PointF[] points = new PointF[2];
					points[0].X = x1;
					points[0].Y = y1page;
					points[1].X = x2;
					points[1].Y = y2page;
					_G.DrawLines(pen, points);
				}
			}

			public void DrawString(string s, Font printFont, Brush brush, Single x, Single y, Single w, Single h)
			{
				DrawString(s, printFont, brush, x, y, w, h, new StringFormat());
			}

			public void DrawString(string s, Font printFont, Brush brush, Single x, Single y, Single w, Single h, StringFormat sf)
			{
				if (PrintUnitIsInCurrentPage())
				{
					Single yPage = _ConvertToPage(y);
					RectangleF r = new RectangleF();
					r.X = x;
					r.Y = yPage;
					r.Width = w;
					r.Height = h;
					_G.DrawString(s, printFont, brush, r, sf);
				}
			}

			public void DrawRectangle(Pen pen, Single x, Single y, Single w, Single h)
			{
				if (PrintUnitIsInCurrentPage())
				{
					Single yPage = _ConvertToPage(y);
					_G.DrawRectangle(pen, x, yPage, w, h);
				}
			}

			public void DrawEllipse(Pen pen, Single x, Single y, Single w, Single h)
			{
				if (PrintUnitIsInCurrentPage())
				{
					Single yPage = _ConvertToPage(y);
					_G.DrawEllipse(pen, x, yPage, w, h);
				}
			}

			public void FillEllipse(Brush brush, Single x, Single y, Single w, Single h)
			{
				if (PrintUnitIsInCurrentPage())
				{
					Single yPage = _ConvertToPage(y);
					_G.FillEllipse(brush, x, yPage, w, h);
				}
			}

			public void DrawImage(Image image, Single x, Single y, Single w, Single h)
			{
				if (PrintUnitIsInCurrentPage())
				{
					Single yPage = _ConvertToPage(y);
					_G.DrawImage(image, x, yPage, w, h);
				}
			}

			public void DrawFrame(Pen pen, Single x, Single y, Single w, Single h)
			{
				PointF[] points = new PointF[2];
				Single yTop = _CurrentPageTop;
				Single yBottom = _CurrentPageBottom;

				if (y+h <= _CurrentPageTop )	//Bottom of Frame above current page
					return;		
				if (y >= _CurrentPageBottom)	//Top of Frame below current page
				{
					_PageOverflow = true;
					return;		
				}

				// Assign X coordinate for horizontal lines
				points[0].X = x;
				points[1].X = x + w;

				// Draw top line
				if (y >= _CurrentPageTop)	//Top in current page
				{
					yTop = y;
					points[0].Y = _ConvertToPage(yTop);
					points[1].Y = _ConvertToPage(yTop);
					_G.DrawLines(pen, points);
				}

				// Draw bottom line
				if (y+h <= _CurrentPageBottom) //Bottom in current page
				{
					yBottom = y+h;
					points[0].Y = _ConvertToPage(yBottom);
					points[1].Y = _ConvertToPage(yBottom);
					_G.DrawLines(pen, points);
				}
				else
					_PageOverflow = true;

				// Assign Y coordinate for vertical lines
				points[0].Y = _ConvertToPage(yTop);
				points[1].Y = _ConvertToPage(yBottom);

				// Draw left line
				points[0].X = x;
				points[1].X = x;
				_G.DrawLines(pen, points);

				// Draw right line
				points[0].X = x + w;
				points[1].X = x + w;
				_G.DrawLines(pen, points);
			}
		}
	#endregion
	}
}